﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Core.Exception;

namespace Core.Xml.Ogc.Ows
{
    /// <summary>
    /// The ServiceIdentification section of a service metadata document contains 
    /// basic metadata about this specific server. The contents and organization 
    /// of this section should be the same for all OWSs. The ServiceIdentification 
    /// section shall include the parameters and parts described in Figure 4 and 
    /// specified in Table 11.
    /// 
    /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, 7.4.4]
    /// </summary>
    class ServiceIdentification : IXmlIsland
    {
        // TODO : Add Profile property, which is also stated in OWS Table 11


        /// <summary>
        /// Title of this server, normally used for display to a human
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        /// <remarks>Mandatory</remarks>
        public List<LanguageStringType> Titles { get; set; }

        /// <summary>
        /// Brief narrative description of this server, normally available for display to 
        /// a human
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        public List<LanguageStringType> Abstracts { get; set; }

        /// <summary>
        /// Unordered list of one or more commonly used or formalised word(s) or phrase(s)
        /// used to describe this server
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        public List<LanguageStringType> Keywords { get; set; }

        /// <summary>
        /// A service type URN from a registry of services, normally used for 
        /// machine-to-machine communication
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        public string ServiceType { get { return "WPS"; } }

        private string[] m_ServiceTypeVersions = new string[] { "1.0.0" };
        /// <summary>
        /// Versions of this service type implemented by this server
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        public string[] ServiceTypeVersions { get { return m_ServiceTypeVersions; } }

        /// <summary>
        /// Fees and terms for using this server, including the monetary 
        /// units as specified in ISO 4217
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        public string Fees { get { return String.Empty; } }

        /// <summary>
        /// Access constraints that should be observed to assure the protection of privacy or 
        /// intellectual property, and any other restrictions on retrieving or using data from 
        /// or otherwise using this server
        /// [cite : OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0, Table 11]
        /// </summary>
        public string AccessConstraints { get { return String.Empty; } }

        public ServiceIdentification()
        {
            // TODO : Clean...
#if DEBUG
            this.Titles = new List<LanguageStringType>() { "GeoWPS" };
            this.Abstracts = new List<LanguageStringType>() { "OWS GetCapabillities ServiceIdentification class mock." };
            this.Keywords = new List<LanguageStringType>();
            this.Keywords.Add("hello");
            this.Keywords.Add("world");
#endif
        }

        /// <summary>
        /// Creates the XElement of the ServiceIdentification as stated in the "OGC 06-121r9, OGC Web Services Common Standard, Version: 2.0.0"
        /// </summary>
        /// <returns></returns>
        public XElement CreateXElement()
        {
            XElement serviceIdentification = new XElement(Namespaces.OWS + "ServiceIdentification");
            if (this.Titles == null || this.Titles.Count == 0)
                throw new FieldCanNotBeNullException(0x000000, "ServiceIdentification XML can not contain empty Titles.");

            foreach (LanguageStringType title in Titles)
                serviceIdentification.Add(title.CreateXElement(Namespaces.OWS + "Title"));

            foreach (LanguageStringType _abstract in Abstracts)
                serviceIdentification.Add(_abstract.CreateXElement(Namespaces.OWS + "Abstract"));

            if (Keywords.Count > 0)
                serviceIdentification.Add(CreateKeywordsXElement());

            serviceIdentification.Add(new XElement(Namespaces.OWS + "ServiceType", this.ServiceType));
            foreach (string serviceTypeVersion in ServiceTypeVersions)
                serviceIdentification.Add(new XElement(Namespaces.OWS + "ServiceTypeVersion", serviceTypeVersion));

            if (this.Fees != String.Empty)
                serviceIdentification.Add(new XElement(Namespaces.OWS + "Fees", this.Fees));

            if (this.AccessConstraints != String.Empty)
                serviceIdentification.Add(new XElement(Namespaces.OWS + "AccessConstraints", this.AccessConstraints));

            return serviceIdentification;
        }

        private XElement CreateKeywordsXElement()
        {
            XElement keywords = new XElement(Namespaces.OWS + "Keywords");
            foreach (LanguageStringType keyword in Keywords)
                keywords.Add(keyword.CreateXElement(Namespaces.OWS + "Keyword"));
            return keywords;
        }
    }
}
